<template>
  <div style="width: 100%; height: 90vh; display: flex; flex-direction: column;">
    <div style="display: flex; justify-content: space-between; align-items: center; padding: 0 10px; margin: 5px 0;">
      <h2 style="margin: 0;">全国景点地图</h2>
      <div>
        <select v-model="heatmapRadius" style="margin-right: 10px; padding: 3px 5px;">
          <option value="10">小范围</option>
          <option value="15" selected>中范围</option>
          <option value="20">大范围</option>
        </select>
        <select v-model="heatmapBlur" style="margin-right: 10px; padding: 3px 5px;">
          <option value="5" selected>低模糊度</option>
          <option value="10">中模糊度</option>
          <option value="15">高模糊度</option>
        </select>
        <select v-model="heatmapWeight" style="padding: 3px 5px;">
          <option value="1" selected>基础密度</option>
          <option value="2">2倍密度</option>
          <option value="3">3倍密度</option>
          <option value="5">5倍密度</option>
        </select>
      </div>
    </div>

    <div id="map" ref="mapContainer" style="flex: 1; border: 1px solid #ccc; background: #f0f0f0;"></div>

    <!-- 热力图开关 -->
    <div style="display: flex; justify-content: center; margin-top: 10px;">
      <button @click="toggleHeatmap" style="padding: 5px 15px; cursor: pointer;">
        {{ showHeatmap ? '切换到景点标记' : '切换到热力图' }}
      </button>
    </div>

    <!-- 景点详情信息窗口 -->
    <div
        v-if="selectedFeature"
        class="ol-popup"
        :style="{ left: popupPosition.x + 'px', top: popupPosition.y + 'px' }"
        style="position: absolute; z-index: 1000;"
    >
      <div class="ol-popup-content">
        <h3>{{ selectedFeature.name }}</h3>
        <p><strong>类型：</strong>{{ selectedFeature.type }}</p>
        <p><strong>地址：</strong>{{ selectedFeature.address }}</p>
        <p><strong>门票：</strong>{{ selectedFeature.ticketPrice }}</p>
        <button @click="closePopup">关闭</button>
      </div>
    </div>
  </div>
  <NavigationBar/>
</template>

<script>
import { ref, onMounted, onUnmounted, watch } from 'vue';
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Heatmap from 'ol/layer/Heatmap';
import { fromLonLat } from 'ol/proj';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import { Style, Icon, Text, Fill, Stroke } from 'ol/style';
import XYZ from 'ol/source/XYZ';
import NavigationBar from "./NavigationBar.vue";
import { ElMessageBox, ElMessage } from 'element-plus';

export default {
  components: { NavigationBar },
  setup() {
    const mapContainer = ref(null);
    const map = ref(null);
    const attractions = ref([]);
    const selectedFeature = ref(null);
    const popupPosition = ref({ x: 0, y: 0 });
    const showHeatmap = ref(true); // 默认显示热力图

    // 热力图参数
    const heatmapRadius = ref(15);
    const heatmapBlur = ref(5);
    const heatmapWeight = ref(1);

    const TIAN_DI_TU_KEY = 'e0544d1d5d87cd63d1f2d0338830974c';

    // 图层变量
    let markerLayer = null;
    let heatmapLayer = null;
    let vectorSource = null;
    let tiandituVecLayer = null;
    let tiandituCvaLayer = null;

    // 拉框选择交互
    let selectBox = null;

    // 存储选中的景点信息（用于弹窗）
    const selectedAttractions = ref([]);

    // 加载景点数据
    const loadAttractions = async () => {
      try {
        const response = await fetch('http://localhost:8088/api/attractions');
        if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
        attractions.value = await response.json();
        console.log('景点数据加载成功:', attractions.value);
        updateHeatmapLayer();
      } catch (error) {
        console.error('加载景点数据失败:', error);
        alert('加载景点数据失败，请刷新页面重试');
      }
    };

    // 初始化地图
    const initMap = () => {
      // 创建矢量数据源
      vectorSource = new VectorSource();

      // 创建景点标记图层
      markerLayer = new VectorLayer({
        source: vectorSource,
        style: (feature) => {
          return new Style({
            image: new Icon({
              src: 'https://cdn-icons-png.flaticon.com/64/684/684908.png',
              size: [64, 64],
              scale: 0.5,
              anchor: [0.5, 1],
            }),
            text: new Text({
              text: feature.get('name'),
              offsetY: -20,
              fill: new Fill({ color: '#000' }),
              stroke: new Stroke({ color: '#fff', width: 2 }),
              font: '12px Microsoft YaHei',
            }),
          });
        },
        visible: false,
      });

      // 创建热力图层
      heatmapLayer = new Heatmap({
        source: vectorSource,
        radius: parseInt(heatmapRadius.value),
        blur: parseInt(heatmapBlur.value),
        weight: 'weight',
        opacity: 0.7,
        visible: true,
      });

      // 天地图图层
      tiandituVecLayer = new TileLayer({
        source: new XYZ({
          url: `https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIAN_DI_TU_KEY}`
        })
      });

      tiandituCvaLayer = new TileLayer({
        source: new XYZ({
          url: `https://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${TIAN_DI_TU_KEY}`
        })
      });

      // 初始化地图
      map.value = new Map({
        target: mapContainer.value,
        layers: [
          tiandituVecLayer,
          tiandituCvaLayer,
          heatmapLayer,
          markerLayer,
        ],
        view: new View({
          center: fromLonLat([104.0657, 30.6598]),
          zoom: 12,
          minZoom: 3,
          maxZoom: 18,
        }),
      });

      // 添加点击事件（弹出单个景点信息）
      map.value.on('click', (event) => {
        const feature = map.value.forEachFeatureAtPixel(event.pixel, (feat) => feat);
        if (feature) {
          const coordinate = event.coordinate;
          const pixel = map.value.getPixelFromCoordinate(coordinate);
          popupPosition.value = { x: pixel[0] + 10, y: pixel[1] - 10 };
          selectedFeature.value = feature.getProperties();
        } else {
          selectedFeature.value = null;
        }
      });

      // 初始化拉框选择
      initBoxSelection();
      loadAttractions();
    };

    // 初始化拉框选择
    const initBoxSelection = () => {
      // 监听 shift 键按下/释放，用于触发拉框选择
      let isShiftPressed = false;

      window.addEventListener('keydown', (e) => {
        if (e.key === 'Shift') {
          isShiftPressed = true;
          mapContainer.value.style.cursor = 'crosshair';
        }
      });

      window.addEventListener('keyup', (e) => {
        if (e.key === 'Shift') {
          isShiftPressed = false;
          mapContainer.value.style.cursor = 'grab';
        }
      });

      // 鼠标按下开始绘制矩形
      let startPixel = null;
      const sketch = document.createElement('div');
      sketch.style.cssText = `
        position: absolute;
        border: 2px dashed #f39c12;
        background-color: rgba(243, 156, 18, 0.1);
        pointer-events: none;
        display: none;
        z-index: 1001;
      `;
      document.body.appendChild(sketch);

      const mapEl = mapContainer.value;
      mapEl.style.cursor = 'grab';

      mapEl.addEventListener('mousedown', (event) => {
        if (!isShiftPressed) return;
        startPixel = [event.clientX, event.clientY];
        sketch.style.left = startPixel[0] + 'px';
        sketch.style.top = startPixel[1] + 'px';
        sketch.style.width = '0px';
        sketch.style.height = '0px';
        sketch.style.display = 'block';
      });

      mapEl.addEventListener('mousemove', (event) => {
        if (!startPixel || !isShiftPressed) return;
        const width = event.clientX - startPixel[0];
        const height = event.clientY - startPixel[1];
        sketch.style.width = Math.abs(width) + 'px';
        sketch.style.height = Math.abs(height) + 'px';
        sketch.style.left = (width > 0 ? startPixel[0] : event.clientX) + 'px';
        sketch.style.top = (height > 0 ? startPixel[1] : event.clientY) + 'px';
      });

      mapEl.addEventListener('mouseup', (event) => {
        if (!startPixel || !isShiftPressed) return;

        const endPixel = [event.clientX, event.clientY];
        const minX = Math.min(startPixel[0], endPixel[0]);
        const minY = Math.min(startPixel[1], endPixel[1]);
        const maxX = Math.max(startPixel[0], endPixel[0]);
        const maxY = Math.max(startPixel[1], endPixel[1]);

        // 清除框选视觉
        sketch.style.display = 'none';
        startPixel = null;

        // 获取地图视图的 extent（屏幕像素 -> 地理坐标范围）
        const view = map.value.getView();
        const topLeft = map.value.getCoordinateFromPixel([minX, minY]);
        const bottomRight = map.value.getCoordinateFromPixel([maxX, maxY]);

        if (!topLeft || !bottomRight) return;

        const extent = [
          topLeft[0], bottomRight[1], // 左上角 x, 右下角 y
          bottomRight[0], topLeft[1]  // 右下角 x, 左上角 y
        ];

        // 查找在范围内的景点
        const featuresInExtent = vectorSource.getFeaturesInExtent(extent);
        if (featuresInExtent.length === 0) {
          ElMessage.info('未选中任何景点');
          return;
        }

        // 提取景点信息
        selectedAttractions.value = featuresInExtent.map(feat => feat.getProperties());

        // 显示弹窗
        showSelectionDialog();
      });
    };

    // 显示选中景点的弹窗
    const showSelectionDialog = () => {
      const content = `
        <div style="max-height: 400px; overflow-y: auto; padding-right: 10px;">
          <h3 style="text-align: center; margin-bottom: 15px;">选中的景点（共 ${selectedAttractions.value.length} 个）</h3>
          <ul style="list-style: none; padding: 0;">
            ${selectedAttractions.value.map((spot, idx) => `
              <li style="border-bottom: 1px solid #eee; padding: 8px 0;">
                <strong>${idx + 1}. ${spot.name}</strong><br>
                类型：${spot.type || '未知'}<br>
                地址：${spot.address || '未知'}<br>
                门票：${spot.ticketPrice || '未知'}
              </li>
            `).join('')}
          </ul>
        </div>
      `;

      ElMessageBox({
        title: '景点选择结果',
        message: content,
        dangerouslyUseHTMLString: true,
        showClose: true,
        closeOnClickModal: true,
        confirmButtonText: '关闭',
        customClass: 'selection-dialog',
        width: '500px',
      }).catch(() => {
        // 用户点击遮罩或取消，静默处理
      });
    };

    // 更新热力图数据
    const updateHeatmapLayer = () => {
      if (!vectorSource) return;
      vectorSource.clear();
      attractions.value.forEach((spot) => {
        const feature = new Feature({
          geometry: new Point(fromLonLat([spot.longitude, spot.latitude])),
          name: spot.name,
          type: spot.type,
          address: spot.address,
          ticketPrice: spot.ticketPrice,
          weight: parseFloat(heatmapWeight.value) || 1,
        });
        vectorSource.addFeature(feature);
      });
    };

    // 切换热力图/标记视图
    const toggleHeatmap = () => {
      if (showHeatmap.value) {
        heatmapLayer.setVisible(false);
        markerLayer.setVisible(true);
        showHeatmap.value = false;
      } else {
        markerLayer.setVisible(false);
        heatmapLayer.setVisible(true);
        showHeatmap.value = true;
        updateHeatmapLayer();
      }
    };

    // 关闭弹窗
    const closePopup = () => {
      selectedFeature.value = null;
    };

    // 组件挂载时初始化地图
    onMounted(() => {
      initMap();

      watch(
          [heatmapRadius, heatmapBlur, heatmapWeight],
          ([radius, blur, weight]) => {
            if (showHeatmap.value && heatmapLayer) {
              heatmapLayer.setRadius(parseInt(radius));
              heatmapLayer.setBlur(parseInt(blur));
              updateHeatmapLayer();
            }
          }
      );
    });

    // 组件卸载时清理
    onUnmounted(() => {
      if (map.value) {
        map.value.setTarget(null);
      }
    });

    return {
      mapContainer,
      selectedFeature,
      popupPosition,
      closePopup,
      heatmapRadius,
      heatmapBlur,
      heatmapWeight,
      showHeatmap,
      toggleHeatmap
    };
  },
};
</script>

<style>
.ol-popup {
  position: absolute;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 10px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
  z-index: 1000;
  max-width: 300px;
  font-size: 14px;
}

.ol-popup:after,
.ol-popup:before {
  top: 100%;
  border: solid transparent;
  content: ' ';
  height: 0;
  width: 0;
  position: absolute;
  pointer-events: none;
}

.ol-popup:after {
  border-top-color: white;
  border-width: 10px;
  margin-left: -10px;
}

.ol-popup:before {
  border-top-color: #ccc;
  border-width: 11px;
  margin-left: -11px;
}

.ol-popup-content button {
  margin-top: 8px;
  padding: 4px 8px;
  font-size: 12px;
}

select {
  padding: 4px 6px;
  border-radius: 3px;
  border: 1px solid #ccc;
  font-size: 14px;
}

button {
  padding: 5px 10px;
  background-color: #409eff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

button:hover {
  background-color: #66b1ff;
}
</style>